package com.sunshine.lnuplusweb.utils;

import com.sunshine.lnuplusweb.callback.LoginCallback;
import com.sunshine.lnuplusweb.entities.Lesson;
import kotlin.Pair;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.*;

/**
 * 登录辽宁大学教务管理
 */
public class ImportLessonByLNU {

    private String userId;

    private String password;

    private int scheduleId;

    /**
     * 构造函数
     * @param userId        登录教务管理的账号
     * @param password      登录教务管理的密码
     * @param scheduleId    课表id，用于设置解析出来的课程导入哪个课表
     */
    public ImportLessonByLNU(String userId, String password, int scheduleId) {
        this.userId = userId;
        this.password = password;
        this.scheduleId = scheduleId;
    }

    /**
     * 采用OkHttp3进行网络请求，获取cookie
     * @param callback      登录结果回调给调用者
     */
    public void load(LoginCallback<List<Lesson>> callback){
        //todo 这为什么不能这么用
//        OkHttpClient okHttpClient = new OkHttpClient();
//        okHttpClient
//                .newBuilder()
//                .followRedirects(false)
//                .build();
        OkHttpClient okHttpClient =
                new OkHttpClient().newBuilder()
                .followRedirects(false)
                .build();
        FormBody requestBody = new FormBody.Builder()
                .add("stuid", userId)
                .add("pwd", password)
                .build();
        Request request = new Request.Builder()
                .url("http://jwgl.lnu.edu.cn/pls/wwwbks/bks_login2.login")
                .post(requestBody)
                .build();

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onFail("没有网络连接");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                Headers headers = response.headers();
                String cookie = "";
                for (Pair<? extends String, ? extends String> header : headers) {
                    if (header.getFirst().equals("Set-Cookie")) {
                        cookie = header.getSecond();
                    }
                }
                //用户名或密码错误
                if (cookie.length() <= 0) {
                    callback.onFail("用户名或密码错误");
                } else {
                    load1(callback, cookie);
                }
            }
        });
    }

    /**
     * 获取到cookie进行课表获取
     * @param callback      回调
     * @param cookie        cookie
     */
    private void load1(LoginCallback<List<Lesson>> callback, String cookie) {
        OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient
                .newBuilder()
                .build();
        Request request = new Request.Builder()
                .url("http://jwgl.lnu.edu.cn/pls/wwwbks/xk.CourseView")
                .header("Cookie", cookie)
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onFail("获取课表失败");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                ResponseBody responseBody = response.body();
                if (null == responseBody) {
                    callback.onFail("获取课表失败");
                } else {
                    Document document = Jsoup.parse(responseBody.string());
                    Elements htmlLesson = document.select("td[bgcolor=\"#EAE2F3\"]");
                    //捕获解析课程时出现的异常
                    try {
                        parseLNULesson(htmlLesson, callback);
                    } catch (Exception e) {
                        e.printStackTrace();
                        callback.onFail("解析课程时出现问题。发现的问题如下：\n" + e.toString());
                    }
                }
            }
        });
    }

    /**
     * 从网页中解析出课程信息
     * ps:懒了，直接用的Android端一年前的解析课程方法，很low，但是结果是对的
     * @param htmlLesson        含有课程html代码的元素集合
     * @param callback          回调
     */
    public void parseLNULesson(Elements htmlLesson, LoginCallback<List<Lesson>> callback) throws Exception{
        //用于存储解析出来的课程信息
        List<Lesson> lessonList = new ArrayList<>();

        //筛选，小于50用于解析教师，大于50用于解析课程具体信息
        int count = 0;

        //教师和课程对应表
        Map<String, String> map = new HashMap<>();

        //0课程名称，1时间，2地点，3周数，4课号
        String[] classInfo = new String[5];

        for (Element element : htmlLesson) {
            //解析教师
            if (++count < 50) {
                ArrayList<String> teacherInfo = new ArrayList<>();
                String info =
                        element.text()
                        .replace("(必修)", "")
                        .replace("(限选)", "")
                        .replace("(任选)", "");
                //判断当前时间是否有课
                if (info.length() > 0) {
                    for (String s : info.split(" ")) {
                        if (s.contains("/")) {
                            teacherInfo.addAll(Arrays.asList(s.split("/")));
                            map.put(teacherInfo.get(0), teacherInfo.get(1));
                        }
                    }
                }
            }
            //解析课程
            else {
                String info = element.toString()
                        .replace("<td bgcolor=\"#EAE2F3\"><p align=\"center\">", "")
                        .replace("<br>", "")
                        .replaceAll("<font color=\"#FF0000\">(.*)</font>", "")
                        .replace("&nbsp;</p></td>", "")
                        .replace("全周上课", "1-16")
                        .replace("单周上课", "1,3,5,7,9,11,13,15")
                        .replace("双周上课", "2,4,6,8,10,12,14,16")
                        .replace(",周上", "")
                        .replace("周上", "");
                switch ((count-50)%9){
                    case 0:
                        classInfo[0] = info;
                        break;
                    case 2:
                        classInfo[4] = info;
                        break;
                    case 6:
                        classInfo[2] = info;
                        break;
                    case 7:
                        classInfo[1] = info;
                        break;
                    case 8:
                        classInfo[3] = info;
                        //如果是1-16等这种的课程，我们把它转变为逗号分割的，这样好处理
                        if (classInfo[3].contains("-")){
                            StringBuilder weekTemp = new StringBuilder();
                            for (int i = Integer.parseInt(classInfo[3].split("-")[0]); i <= Integer.parseInt(classInfo[3].split("-")[1]); i++) {
                                weekTemp.append(i).append(",");
                            }
                            classInfo[3] = weekTemp.substring(0, weekTemp.length() - 1);
                        }
                        //0 : 周几，1 : 第几节开始
                        String[] time = classInfo[1].split("-");
                        Lesson lesson = new Lesson(
                                scheduleId,                 //课表id
                                classInfo[4],                               //课程编号
                                Integer.valueOf(time[0]),                   //周几
                                Integer.parseInt(time[1]),
                                0L,
                                Integer.parseInt(time[1]),
                                0L,
                                classInfo[0],                               //课程名称
                                map.get(classInfo[0]),                      //老师
                                classInfo[2],                               //地点
                                classInfo[3],                               //周数
                                "0"
                        );
                        lessonList.add(lesson);
                }
            }
        }

        callback.onSuccess(lessonList);
    }
}
